home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE2 / PD / VINCE / !ViNCe / c / tight16 < prev    next >
Text File  |  2002-03-10  |  10KB  |  373 lines

  1. /*
  2.  *  Copyright (C) 2000 Const Kaplinsky.  All Rights Reserved.
  3.  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
  4.  *
  5.  *  This is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This software is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this software; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18.  *  USA.
  19.  */
  20.  
  21. /*
  22.  * tight.c - handle ``tight'' encoding.
  23.  *
  24.  * This file shouldn't be compiled directly. It is included multiple
  25.  * times by rfbproto.c, each time with a different definition of the
  26.  * macro BPP. For each value of BPP, this file defines a function
  27.  * which handles an zlib encoded rectangle with BPP bits per pixel.
  28.  *
  29.  */
  30.  
  31. #define TIGHT_MIN_TO_COMPRESS 12
  32.  
  33. #ifndef RGB_TO_PIXEL
  34.  
  35. #define RGB_TO_PIXEL(bpp,r,g,b)                                              \
  36.   ((CARD16)(r) & myFormat.redMax) << myFormat.redShift |                  \
  37.   ((CARD16)(g) & myFormat.greenMax) << myFormat.greenShift |              \
  38.   ((CARD16)(b) & myFormat.blueMax) << myFormat.blueShift;
  39.  
  40. #define RGB24_TO_PIXEL32(r,g,b)                                              \
  41.   ((CARD32)(r) & 0xFF) << myFormat.redShift |                                \
  42.   ((CARD32)(g) & 0xFF) << myFormat.greenShift |                              \
  43.   ((CARD32)(b) & 0xFF) << myFormat.blueShift;
  44.  
  45. #endif
  46.  
  47. /* Type declarations */
  48.  
  49. typedef void (*filterPtr16)(int, CARD16 *);
  50.  
  51. /* Prototypes */
  52.  
  53. static int InitFilterCopy16 (int rw, int rh);
  54. static int InitFilterPalette16 (int rw, int rh);
  55. static int InitFilterGradient16 (int rw, int rh);
  56. static void FilterCopy16 (int numRows, CARD16 *destBuffer);
  57. static void FilterPalette16 (int numRows, CARD16 *destBuffer);
  58. static void FilterGradient16 (int numRows, CARD16 *destBuffer);
  59.  
  60. /* Definitions */
  61.  
  62. static Bool HandleTight16 (int rx, int ry, int rw, int rh) {
  63.   CARD16 fill_colour;
  64.   CARD8 comp_ctl;
  65.   CARD8 filter_id;
  66.   filterPtr16 filterFn;
  67.   z_streamp zs;
  68.   char *buffer2;
  69.   int err, stream_id, bitsPixel;
  70.   int bufferSize, rowSize, numRows, rowsProcessed, extraBytes;
  71.   int compressedLen, portionLen;
  72.  
  73.   if (!ReadFromRFBServer((char *)&comp_ctl, 1))
  74.     return False;
  75.  
  76.   /* Flush zlib streams if we are told by the server to do so. */
  77.   for (stream_id = 0; stream_id < 4; stream_id++) {
  78.     if ((comp_ctl & 1) && zlibStreamActive[stream_id]) {
  79.       if (inflateEnd (&zlibStream[stream_id]) != Z_OK &&
  80.           zlibStream[stream_id].msg != NULL)
  81.         fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg);
  82.       zlibStreamActive[stream_id] = False;
  83.     }
  84.     comp_ctl >>= 1;
  85.   }
  86.  
  87.   /* Handle solid rectangles. */
  88.   if (comp_ctl == rfbTightFill) {
  89.     if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour)))
  90.         return False;
  91.  
  92. //    gcv.foreground = fill_colour;
  93.     display_fillrectangle(rx, ry, rw, rh, fill_colour);
  94.     return True;
  95.   }
  96.  
  97.   /* Quit on unsupported subencoding value. */
  98.   if (comp_ctl > rfbTightMaxSubencoding) {
  99.     fprintf(stderr, "Tight encoding: bad subencoding value received.\n");
  100.     return False;
  101.   }
  102.  
  103.   /*
  104.    * Here primary compression mode handling begins.
  105.    * Data was processed with optional filter + zlib compression.
  106.    */
  107.  
  108.   /* First, we should identify a filter to use. */
  109.   if ((comp_ctl & rfbTightExplicitFilter) != 0) {
  110.     if (!ReadFromRFBServer((char*)&filter_id, 1))
  111.       return False;
  112.  
  113.     switch (filter_id) {
  114.     case rfbTightFilterCopy:
  115.       filterFn = FilterCopy16;
  116.       bitsPixel = InitFilterCopy16(rw, rh);
  117.       break;
  118.     case rfbTightFilterPalette:
  119.       filterFn = FilterPalette16;
  120.       bitsPixel = InitFilterPalette16(rw, rh);
  121.       break;
  122.     case rfbTightFilterGradient:
  123.       filterFn = FilterGradient16;
  124.       bitsPixel = InitFilterGradient16(rw, rh);
  125.       break;
  126.     default:
  127.       fprintf(stderr, "Tight encoding: unknown filter code received.\n");
  128.       return False;
  129.     }
  130.   } else {
  131.     filterFn = FilterCopy16;
  132.     bitsPixel = InitFilterCopy16(rw, rh);
  133.   }
  134.   if (bitsPixel == 0) {
  135.     fprintf(stderr, "Tight encoding: error receiving palette.\n");
  136.     return False;
  137.   }
  138.  
  139.   /* Determine if the data should be decompressed or just copied. */
  140.   rowSize = (rw * bitsPixel + 7) / 8;
  141.   if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) {
  142.     if (!ReadFromRFBServer((char*)buffer, rh * rowSize))
  143.       return False;
  144.  
  145.     buffer2 = &buffer[TIGHT_MIN_TO_COMPRESS * 4];
  146.     filterFn(rh, (CARD16 *)buffer2);
  147.     display_raw(rx, ry, rw, rh, buffer2, 0);
  148. //    CopyDataToScreen(buffer2, rx, ry, rw, rh);
  149.     return True;
  150.   }
  151.  
  152.   /* Read the length (1..3 bytes) of compressed data following. */
  153.   compressedLen = (int)ReadCompactLen();
  154.   if (compressedLen <= 0) {
  155.     fprintf(stderr, "Incorrect data received from the server.\n");
  156.     return False;
  157.   }
  158.  
  159.   /* Now let's initialize compression stream if needed. */
  160.   stream_id = comp_ctl & 0x03;
  161.   zs = &zlibStream[stream_id];
  162.   if (!zlibStreamActive[stream_id]) {
  163.     zs->zalloc = Z_NULL;
  164.     zs->zfree = Z_NULL;
  165.     zs->opaque = Z_NULL;
  166.     err = inflateInit(zs);
  167.     if (err != Z_OK) {
  168.       if (zs->msg != NULL)
  169.         fprintf(stderr, "InflateInit error: %s.\n", zs->msg);
  170.       return False;
  171.     }
  172.     zlibStreamActive[stream_id] = True;
  173.   }
  174.  
  175.   /* Read, decode and draw actual pixel data in a loop. */
  176.  
  177.   bufferSize = BUFFER_SIZE * bitsPixel / (bitsPixel + 16) & 0xFFFFFFFC;
  178.   buffer2 = &buffer[bufferSize];
  179.   if (rowSize > bufferSize) {
  180.     /* Should be impossible when BUFFER_SIZE >= 16384 */
  181.     fprintf(stderr, "Internal error: incorrect buffer size.\n");
  182.     return False;
  183.   }
  184.  
  185.   rowsProcessed = 0;
  186.   extraBytes = 0;
  187.  
  188.   while (compressedLen > 0) {
  189.     if (compressedLen > ZLIB_BUFFER_SIZE)
  190.       portionLen = ZLIB_BUFFER_SIZE;
  191.     else
  192.       portionLen = compressedLen;
  193.  
  194.     if (!ReadFromRFBServer((char*)zlib_buffer, portionLen))
  195.       return False;
  196.  
  197.     compressedLen -= portionLen;
  198.  
  199.     zs->next_in = (Bytef *)zlib_buffer;
  200.     zs->avail_in = portionLen;
  201.  
  202.     do {
  203.       zs->next_out = (Bytef *)&buffer[extraBytes];
  204.       zs->avail_out = bufferSize - extraBytes;
  205.  
  206.       err = inflate(zs, Z_SYNC_FLUSH);
  207.       if (err != Z_OK && err != Z_STREAM_END) {
  208.         if (zs->msg != NULL)
  209.           fprintf(stderr, "Inflate error: %s.\n", zs->msg);
  210.         return False;
  211.       }
  212.  
  213.       numRows = (bufferSize - zs->avail_out) / rowSize;
  214.  
  215.       filterFn(numRows, (CARD16 *)buffer2);
  216.  
  217.       extraBytes = bufferSize - zs->avail_out - numRows * rowSize;
  218.       if (extraBytes > 0)
  219.         memcpy(buffer, &buffer[numRows * rowSize], extraBytes);
  220.  
  221.       display_raw(rx, ry + rowsProcessed, rw, numRows, buffer2, 0);
  222. //      CopyDataToScreen(buffer2, rx, ry + rowsProcessed, rw, numRows);
  223.       rowsProcessed += numRows;
  224.     }
  225.     while (zs->avail_out == 0);
  226.   }
  227.  
  228.   if (rowsProcessed != rh) {
  229.     fprintf(stderr, "Incorrect number of scan lines after decompression.\n");
  230.     return False;
  231.   }
  232.  
  233.   return True;
  234. }
  235.  
  236. /*----------------------------------------------------------------------------
  237.  *
  238.  * Filter stuff.
  239.  *
  240.  */
  241.  
  242. /*
  243.    The following variables are defined in rfbproto.c:
  244.      static Bool cutZeros;
  245.      static int rectWidth, rectColors;
  246.      static CARD8 tightPalette[256*4];
  247.      static CARD8 tightPrevRow[2048*3*sizeof(CARD16)];
  248. */
  249.  
  250. static int
  251. InitFilterCopy16 (int rw, int rh)
  252. {
  253.   rectWidth = rw;
  254.  
  255.   return 16;
  256. }
  257.  
  258. static void
  259. FilterCopy16 (int numRows, CARD16 *dst)
  260. {
  261.  
  262.   memcpy (dst, buffer, numRows * rectWidth * (16 / 8));
  263. }
  264.  
  265. static int
  266. InitFilterGradient16 (int rw, int rh)
  267. {
  268.   int bits;
  269.  
  270.   bits = InitFilterCopy16(rw, rh);
  271.   if (cutZeros)
  272.     memset(tightPrevRow, 0, rw * 3);
  273.   else
  274.     memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16));
  275.  
  276.   return bits;
  277. }
  278.  
  279. static void
  280. FilterGradient16 (int numRows, CARD16 *dst)
  281. {
  282.   int x, y, c;
  283.   CARD16 *src = (CARD16 *)buffer;
  284.   CARD16 *thatRow = (CARD16 *)tightPrevRow;
  285.   CARD16 thisRow[2048*3];
  286.   CARD16 pix[3];
  287.   CARD16 max[3];
  288.   int shift[3];
  289.   int est[3];
  290.  
  291.   max[0] = myFormat.redMax;
  292.   max[1] = myFormat.greenMax;
  293.   max[2] = myFormat.blueMax;
  294.  
  295.   shift[0] = myFormat.redShift;
  296.   shift[1] = myFormat.greenShift;
  297.   shift[2] = myFormat.blueShift;
  298.  
  299.   for (y = 0; y < numRows; y++) {
  300.  
  301.     /* First pixel in a row */
  302.     for (c = 0; c < 3; c++) {
  303.       pix[c] = (CARD16)((src[y*rectWidth] >> shift[c]) + thatRow[c] & max[c]);
  304.       thisRow[c] = pix[c];
  305.     }
  306.     dst[y*rectWidth] = RGB_TO_PIXEL(16, pix[0], pix[1], pix[2]);
  307.  
  308.     /* Remaining pixels of a row */
  309.     for (x = 1; x < rectWidth; x++) {
  310.       for (c = 0; c < 3; c++) {
  311.         est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c];
  312.         if (est[c] > (int)max[c]) {
  313.           est[c] = (int)max[c];
  314.         } else if (est[c] < 0) {
  315.           est[c] = 0;
  316.         }
  317.         pix[c] = (CARD16)((src[y*rectWidth+x] >> shift[c]) + est[c] & max[c]);
  318.         thisRow[x*3+c] = pix[c];
  319.       }
  320.       dst[y*rectWidth+x] = RGB_TO_PIXEL(16, pix[0], pix[1], pix[2]);
  321.     }
  322.     memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16));
  323.   }
  324. }
  325.  
  326. static int
  327. InitFilterPalette16 (int rw, int rh)
  328. {
  329. //  int i;
  330.   CARD8 numColors;
  331. //  CARD16 *palette = (CARD16 *)tightPalette;
  332.  
  333.   rectWidth = rw;
  334.  
  335.   if (!ReadFromRFBServer((char*)&numColors, 1))
  336.     return 0;
  337.  
  338.   rectColors = (int)numColors;
  339.   if (++rectColors < 2)
  340.     return 0;
  341.  
  342.   if (!ReadFromRFBServer((char*)&tightPalette, rectColors * (16 / 8)))
  343.     return 0;
  344.  
  345.   return (rectColors == 2) ? 1 : 8;
  346. }
  347.  
  348. static void
  349. FilterPalette16 (int numRows, CARD16 *dst)
  350. {
  351.   int x, y, b, w;
  352.   CARD8 *src = (CARD8 *)buffer;
  353.   CARD16 *palette = (CARD16 *)tightPalette;
  354.  
  355.   if (rectColors == 2) {
  356.     w = (rectWidth + 7) / 8;
  357.     for (y = 0; y < numRows; y++) {
  358.       for (x = 0; x < rectWidth / 8; x++) {
  359.         for (b = 7; b >= 0; b--)
  360.           dst[y*rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
  361.       }
  362.       for (b = 7; b >= 8 - rectWidth % 8; b--) {
  363.         dst[y*rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
  364.       }
  365.     }
  366.   } else {
  367.     for (y = 0; y < numRows; y++)
  368.       for (x = 0; x < rectWidth; x++)
  369.         dst[y*rectWidth+x] = palette[(int)src[y*rectWidth+x]];
  370.   }
  371. }
  372.  
  373.